﻿using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.Practices.Prism;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Regions;
using Sautom.ClientComunication;
using Sautom.ClientComunication.CommandService;
using Sautom.ClientComunication.QueriesService;
using Sautom.ClientComunication.Services;

namespace Sautom.Modules.Client.ViewModels
{
    public sealed class ContractEditViewModel : NavigationAwareNotificationObject
    {
        #region Constructor
        public ContractEditViewModel(IRegionManager regionManager, ServiceFactory serviceFactory)
        {
            RegionManager = regionManager;

            QueriesServiceClient = serviceFactory.GetQueriesService();
            CommandServiceClient = serviceFactory.GetCommandsService();

            BackCommand = new DelegateCommand(ExecuteBackCommand);
            SaveCommand = new DelegateCommand(ExecuteSaveCommand);
        }

        #endregion

        #region Commands
        public DelegateCommand SaveCommand { get; private set; }
        public DelegateCommand BackCommand { get; private set; }

        private void ExecuteSaveCommand()
        {
            //Mapper.CreateMap<DateTime?, DateTime?>().ForAllMembers(d => d.ResolveUsing(o => o != default(DateTime) ? o : null));
            Mapper.CreateMap<ContractEditViewModel, ContractEditDtoInput>();
            Mapper.CreateMap<RateItemDtoOutput, RateItemDtoInput>();
            var contract = Mapper.Map<ContractEditDtoInput>(this);

            CommandServiceClient.EditOrAddContract(contract);

            ExecuteBackCommand();
        }

        private void ExecuteBackCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.ClientId.ToString() }, { "orderId", this.OrderId.ToString() } };
            var uri = new Uri(PathProvider.ContractView + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);
        }
        #endregion

        #region Properties
        private IRegionManager RegionManager { get; set; }
        private IQueriesService QueriesServiceClient { get; set; }
        private ICommandService CommandServiceClient { get; set; }
        #endregion

        #region ViewModel Properties
        public Guid Id { get; set; }

        //consulting section
        private string _consultingNumber;
        public string ConsultingNumber
        {
            get { return _consultingNumber; }
            set
            {
                _consultingNumber = value;
                RaisePropertyChanged(() => ConsultingNumber);
            }
        }

        private DateTime? _consultingDate;
        public DateTime? ConsultingDate
        {
            get { return _consultingDate; }
            set
            {
                _consultingDate = value;
                RaisePropertyChanged(() => ConsultingDate);
                RaisePropertyChanged(() => ConsultingSum);
            }
        }

        private float _consultingHours;
        public float ConsultingHours
        {
            get { return _consultingHours; }
            set
            {
                _consultingHours = value;
                RaisePropertyChanged(() => ConsultingHours);
                RaisePropertyChanged(() => ConsultingSum);
            }
        }

        public float ConsultingSum
        {
            get
            {
                if (_consultingDate.HasValue)
                {
                    ConsultingRate = Rate(_consultingDate.Value);

                    return _consultingHours * ConsultingRate.RateValue;
                }

                return 0;
            }
        }

        private DateTime? _consultingActDate;
        public DateTime? ConsultingActDate
        {
            get { return _consultingActDate; }
            set
            {
                _consultingActDate = value;
                RaisePropertyChanged(() => ConsultingActDate);
            }
        }

        private RateItemDtoOutput _consultingRate;
        public RateItemDtoOutput ConsultingRate
        {
            get
            {
                return _consultingRate;
            }
            set
            {
                _consultingRate = value;
                RaisePropertyChanged(() => ConsultingRate);
            }
        }

        //workshop section
        private string _workshopNumber;
        public string WorkshopNumber
        {
            get { return _workshopNumber; }
            set
            {
                _workshopNumber = value;
                RaisePropertyChanged(() => WorkshopNumber);
            }
        }

        private DateTime? _workshopDate;
        public DateTime? WorkshopDate
        {
            get { return _workshopDate; }
            set
            {
                _workshopDate = value;
                RaisePropertyChanged(() => WorkshopDate);
                RaisePropertyChanged(() => WorkshopSum);
            }
        }

        private float _workshopHours;
        public float WorkshopHours
        {
            get { return _workshopHours; }
            set
            {
                _workshopHours = value;
                RaisePropertyChanged(() => WorkshopHours);
                RaisePropertyChanged(() => WorkshopSum);
            }
        }

        public float WorkshopSum
        {
            get
            {
                if (_workshopDate.HasValue)
                {
                    WorkshopRate = Rate(_workshopDate.Value);

                    return _workshopHours * WorkshopRate.RateValue;
                }

                return 0;
            }
        }

        private DateTime? _workshopActDate;
        public DateTime? WorkshopActDate
        {
            get { return _workshopActDate; }
            set
            {
                _workshopActDate = value;
                RaisePropertyChanged(() => WorkshopActDate);
            }
        }

        public RateItemDtoOutput WorkshopRate { get; set; }

        //invoice section
        private DateTime? _invoiceDate;
        public DateTime? InvoiceDate
        {
            get { return _invoiceDate; }
            set
            {
                _invoiceDate = value;
                RaisePropertyChanged(() => InvoiceDate);
            }
        }

        private int _invoiceSum;
        public int InvoiceSum
        {
            get { return _invoiceSum; }
            set
            {
                _invoiceSum = value;
                RaisePropertyChanged(() => InvoiceSum);
            }
        }

        public List<RateItemDtoOutput> Rates { get; set; }

        public Guid OrderId { get; set; }
        public Guid ClientId { get; set; }
        #endregion

        #region INavigationAware

        public override void OnNavigatedTo(NavigationContext navigationContext)
        {
            base.OnNavigatedTo(navigationContext);

            string orderId = navigationContext.Parameters["orderId"];
            string clientId = navigationContext.Parameters["clientId"];
            if (String.IsNullOrWhiteSpace(orderId) || String.IsNullOrWhiteSpace(clientId)) return;

            OrderId = Guid.Parse(orderId);
            ClientId = Guid.Parse(clientId);

            string id = navigationContext.Parameters["contractId"];
            var idGuid = !string.IsNullOrWhiteSpace(id) ? Guid.Parse(id) : Guid.Empty;

            var contract = QueriesServiceClient.ContractForEdit(idGuid);

            Mapper.CreateMap<ContractEditDtoOutput, ContractEditViewModel>();
            Mapper.Map(contract, this);
        }

        #endregion

        #region Private members
        private RateItemDtoOutput Rate(DateTime date)
        {
            return Rates.Where(rec => rec.Date.Date <= date.Date).OrderByDescending(rec => rec.Date).FirstOrDefault() ?? new RateItemDtoOutput() { Date = DateTime.MinValue, RateValue = 0 };
        }
        #endregion
    }
}
